#include <map>
#include "RspHeaderRecvHandlerBase.h"
#include "BeginConnInsDestHandler.h"
#include "HttpResponseHeader.h"

using namespace std;
using namespace log4cplus;

Logger RspHeaderRecvHandlerBase::log=GetLogger(LOG4CPLUS_TEXT("RspHeaderRecvHandlerBase"));

ITransHandler::ExecuteResultCode RspHeaderRecvHandlerBase::Execute(ClientContext &client,OVERLAPPED *ovl)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	SOCKET recvSock;
	WSABUF *recvBuffer;
	OVERLAPPED *recvOvl;
	HttpResponseHeader *responseHeader;
	GetRecvInfo(client,&recvSock,&recvBuffer,&recvOvl,&responseHeader);

	ExecuteResultCode ret=ITransHandler::ExecuteOK;
	DWORD recvCount=0;
	DWORD flags;
	BOOL result=::WSAGetOverlappedResult(recvSock,recvOvl,&recvCount,true,&flags);
	int errCode=::WSAGetLastError();
	if(result)
	{
		if(recvCount==0)
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Receive 0 byte data,exit."),clienSequenceNo);
			return OnExecuteError(client,recvOvl,ITransHandler::ExecuteFinished);
		}
		LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Receive response header data successed(receive %d bytes data),start to parse."),clienSequenceNo,recvCount);
		char *first=recvBuffer->buf;
		char *last=first+recvCount;
		HttpResponseHeader &headerData=*responseHeader;
		headerData.AppendData(first,last);
		if(headerData.IsValid())
		{
			ret=OnHeaderReceiveCompleted(client,recvOvl,headerData);
		}
		else
		{
			LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Receive response header not finished,retry."),clienSequenceNo);
			DWORD flags=0;
			ZeroMemory(recvOvl,sizeof(OVERLAPPED));
			int recvResult = ::WSARecv(recvSock,recvBuffer,1,NULL,&flags,recvOvl,NULL);
			errCode=::WSAGetLastError();
			if(recvResult!=0&&errCode!=WSA_IO_PENDING)
			{
				ret=OnExecuteError(client,recvOvl,ITransHandler::ExecuteFatalError);
				LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Begin receive response header data failed,error code:%d."),clienSequenceNo,errCode);
			}
		}
	}
	else
	{
		ret=OnExecuteError(client,recvOvl,ITransHandler::ExecuteFatalError);
		LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]End receive server response header failed,error code:%d."),clienSequenceNo,errCode);
	}
	return ret;
}

ITransHandler::ExecuteResultCode RspHeaderRecvHandlerBase::OnHeaderReceiveCompleted(ClientContext &client,OVERLAPPED *ovl,HttpResponseHeader &headerData)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	ExecuteResultCode ret=ITransHandler::ExecuteOK;
	if(!headerData.SetRequestRangeWithCheck(client.TranslatedFileIndex(),client.MaxFileIndex()))
	{
		LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Response is ok,but set request range and check failed."),clienSequenceNo);
		ret=OnExecuteError(client,ovl,ITransHandler::ExecuteFatalError);
	}
	else
	{
		LOG4CPLUS_DEBUG_FMT(log,LOG4CPLUS_TEXT("[Client%d]Receive all response header data successed,start to transfer."),clienSequenceNo);
		ret=OnSendResponseHeader(client,headerData);
	}
	return ret;
}

ITransHandler::ExecuteResultCode RspHeaderRecvHandlerBase::OnSendResponseHeader(ClientContext &client,HttpResponseHeader &headerData)
{
	unsigned int clienSequenceNo=client.SequenceNo();
	if(headerData.TempBuffer().size()>client.Buffer()->len)
	{
		memcpy_s(client.Buffer()->buf,client.Buffer()->len,headerData.TempBuffer().c_str(),client.Buffer()->len);
		client.WeakRefBuffer()->buf=client.Buffer()->buf;
		client.WeakRefBuffer()->len=client.Buffer()->len;
		client.SetPartialTransIndex(client.Buffer()->len);
	}
	else
	{
		memcpy_s(client.Buffer()->buf,client.Buffer()->len,headerData.TempBuffer().c_str(),headerData.TempBuffer().size());
		client.WeakRefBuffer()->buf=client.Buffer()->buf;
		client.WeakRefBuffer()->len=headerData.TempBuffer().size();
		client.SetPartialTransIndex(0);
	}
	delete client.SetCurrentHandler(GetNextHandler());
	::ZeroMemory(client.OVL(),sizeof(OVERLAPPED));
	int sendResult=::WSASend(client.SrcSock(),client.WeakRefBuffer(),1,NULL,0,client.OVL(),NULL);
	int errCode=::WSAGetLastError();
	if(sendResult!=0&&errCode!=WSA_IO_PENDING)
	{
		LOG4CPLUS_ERROR_FMT(log,LOG4CPLUS_TEXT("[Client%d]Start to send server response header data failed,error code:%d."),clienSequenceNo,errCode);
		return ITransHandler::ExecuteFatalError;
	}
	return ITransHandler::ExecuteOK;
}